package cn.tannn.surenessdemo.controller;

import cn.jdevelops.annotation.mapping.PathRestController;
import cn.jdevelops.entity.basics.vo.SerializableVO;
import cn.jdevelops.exception.annotation.DisposeException;
import cn.jdevelops.result.result.ResultVO;
import cn.tannn.surenessdemo.controller.dto.AddResourceDTO;
import cn.tannn.surenessdemo.controller.dto.UpdateResourceDTO;
import cn.tannn.surenessdemo.controller.vo.AuthRouteVO;
import cn.tannn.surenessdemo.controller.vo.ResourceVO;
import cn.tannn.surenessdemo.user.entity.AuthResource;
import cn.tannn.surenessdemo.user.entity.AuthRoute;
import cn.tannn.surenessdemo.user.service.AuthRouteService;
import cn.tannn.surenessdemo.user.service.ResourceService;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.github.xiaoymin.knife4j.annotations.ApiSupport;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
import java.sql.SQLIntegrityConstraintViolationException;
import java.util.List;
import java.util.Optional;

/**
 * 资源管理
 * 0. 新增资源(不开放客户用
 * 1. 删除资源(不开放客户用
 * 2. 查询资源（接口集合根据类型分组
 * 3. 编辑资源
 * 4. 停启用(拦截，不拦截
 * 5. 搜索
 *
 * @author tnnn
 * @version V1.0
 * @date 2022-07-19 11:26
 */
@PathRestController("resource")
@Slf4j
@Api(tags = "资源管理", value = "资源管理")
@RequiredArgsConstructor
@ApiSupport(order = 5)
public class ResourceController {

    private final ResourceService resourceService;
    private final AuthRouteService authRouteService;


    @ApiOperation(value = "新增资源", notes = "资源管理")
    @PostMapping("addResource")
    @ApiOperationSupport(order = 1)
    public ResultVO<String> addResource(@RequestBody @Validated AddResourceDTO authResource) {
        if (resourceService.addResource(authResource)) {
            if (log.isDebugEnabled()) {
                log.debug("add resource success: {}", authResource);
            }
            return ResultVO.success();
        } else {
            return ResultVO.fail("资源已存在");
        }
    }

    @ApiOperation(value = "更新资源", notes = "资源管理")
    @PostMapping("updateResource")
    @ApiOperationSupport(order = 2)
    public ResultVO<String> updateResource(@RequestBody @Validated UpdateResourceDTO authResource) {
        if (resourceService.updateResource(authResource)) {
            if (log.isDebugEnabled()) {
                log.debug("update resource success: {}", authResource);
            }
            return ResultVO.success();
        } else {
            return ResultVO.fail("资源不存在");
        }
    }


    @ApiOperation(value = "删除资源", notes = "资源管理")
    @GetMapping("/deleteResource/{resourceCode}")
    @ApiOperationSupport(order = 3)
    public ResultVO<String> deleteResource(@PathVariable @NotBlank String resourceCode) {
        if (resourceService.deleteResource(resourceCode)) {
            if (log.isDebugEnabled()) {
                log.debug("delete resource success: {}", resourceCode);
            }
            return ResultVO.success();
        } else {
            log.error("delete resource fail: {}", resourceCode);
            return ResultVO.fail("删除资源失败，请稍后再试");
        }
    }

    @ApiOperation(value = "查询所有资源", notes = "资源管理")
    @GetMapping("findAll")
    @ApiOperationSupport(order = 4)
    public ResultVO<List<ResourceVO>> findAll() {
        Optional<List<AuthResource>> allResource = resourceService.getAllResource();
        return allResource.map(authResources -> ResultVO.successForData(SerializableVO.to(authResources, ResourceVO.class))).orElseGet(() -> ResultVO.fail("暂无资源"));
    }


    @ApiOperation(value = "拦截资源资源(codes不传拦截所有)", notes = "资源管理")
    @PostMapping("enable")
    @ApiOperationSupport(order = 5)
    public ResultVO<String> enable(@RequestBody List<String> resourceCodes) {
        resourceService.enable(resourceCodes);
        return ResultVO.success();
    }

    @ApiOperation(value = "不拦截资源", notes = "资源管理")
    @PostMapping("disabled")
    @ApiOperationSupport(order = 6)
    public ResultVO<String> disabled(@RequestBody @NotEmpty List<String> resourceCodes) {
        resourceService.disabled(resourceCodes);
        return ResultVO.success();
    }


    @ApiOperation(value = "资源新增路由", notes = "资源管理")
    @PostMapping("/authority/route/add")
    @ApiOperationSupport(order = 7)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "routeCode", value = "路由code", type = "String", paramType = "query"),
            @ApiImplicitParam(name = "resourceCode", value = "资源code", type = "String", paramType = "query"),
    })
    @DisposeException(messages = "当前角色已经拥有此资源，请勿重复设置", exceptions = SQLIntegrityConstraintViolationException.class)
    public ResultVO<String> authorityRoleResource(@RequestParam @NotBlank String routeCode,
                                                  @RequestParam @NotBlank String resourceCode) {
        resourceService.authorityResourceRoute(routeCode, resourceCode);
        return ResultVO.success();
    }

    @ApiOperation(value = "资源删除路由", notes = "资源管理")
    @PostMapping("/authority/route/deleter")
    @ApiOperationSupport(order = 8)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "routeCode", value = "路由code", type = "String", paramType = "query"),
            @ApiImplicitParam(name = "resourceCode", value = "资源code", type = "String", paramType = "query"),
    })
    public ResultVO<String> deleteAuthorityRoleResource(@RequestParam @NotBlank String routeCode,
                                                        @RequestParam @NotBlank String resourceCode) {
        resourceService.deleteAuthorityResourceRoute(routeCode, resourceCode);
        return ResultVO.success();
    }

    @ApiOperation(value = "获取资源对应的路由", notes = "资源管理")
    @GetMapping("/routeByResource")
    @ApiOperationSupport(order = 9)
    public ResultVO<List<AuthRouteVO>> routeByResource(@RequestParam @NotBlank String resourceCode) {
        List<AuthRoute> routeOwnRole = authRouteService.getRouteByResource(resourceCode);
        return ResultVO.successForData(SerializableVO.to(routeOwnRole, AuthRouteVO.class));
    }

}
